﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Weka
{
    internal class FieldSerialiserProviderMessage<T, MT> : FieldSerialiserProvider<T>//MT is Message Type
        where MT : class
    {
        private FieldSerialiserProviderMessage() { }

        private ObjectSerialiserProvider<MT> _hCreator;
        public Func<T, MT> Reader { get; set; }

        public static FieldSerialiserProviderMessage<T, MT> Create(Dictionary<Type, ObjectSerialiserProvider> cachedTypeSerlisers, System.Reflection.MethodInfo methodInfo)
        {
            FieldSerialiserProviderMessage<T, MT> q = new FieldSerialiserProviderMessage<T, MT>() { _hCreator = Serliser.GetHCreator<MT>(cachedTypeSerlisers) };
            q.Reader = methodInfo.CreateDelegate<T, MT>();
            return q;
        }

        public override FieldSerialiser<T> CreateFieldSerialiser()
        {
            return new FieldSerialiserMessage<T, MT>() { _h = _hCreator.Create(), Reader = Reader, FieldInfo = FieldInfo };
        }

    }




    internal class FieldSerialiserMessage<T, MT> : FieldSerialiser<T>//MT is Message Type
        where MT : class
    {
        public ObjectSerialiser<MT> _h;
        private MT _value;
        public Func<T, MT> Reader { get; set; }

        public sealed override void ReadValueFromTAndWriteHeader(T value, StreamWrita sw)
        {
            if ((_value = Reader(value)) == null)
                sw.HeaderWrite0();
            else
                sw.HeaderWrite1();
        }
        public sealed override void WriteValue(StreamWrita sw)
        {
            if (_value == null) return;
            _h.WriteFieldData(_value, sw);
            _value = null;
        }
        public sealed override void WriteMetadata(StreamWrita sw)
        {
            base.WriteMetadata(sw);
            _h.WriteFieldMetaData(sw);
        }
    }


    internal class FieldSerialiserProviderMessageList<T, MT> : FieldSerialiserProvider<T>//MT is Message Type
        where MT : class
    {
        private FieldSerialiserProviderMessageList() { }

        private ObjectSerialiserProvider<MT> _hCreator;
        public Func<T, IEnumerable<MT>> Reader { get; set; }

        public static FieldSerialiserProviderMessageList<T, MT> Create(Dictionary<Type, ObjectSerialiserProvider> cachedTypeSerlisers, System.Reflection.MethodInfo methodInfo)
        {
            FieldSerialiserProviderMessageList<T, MT> q = new FieldSerialiserProviderMessageList<T, MT>() { _hCreator = Serliser.GetHCreator<MT>(cachedTypeSerlisers) };
            q.Reader = methodInfo.CreateDelegate<T, IEnumerable<MT>>();
            return q;
        }

        public override FieldSerialiser<T> CreateFieldSerialiser()
        {
            return new FieldSerialiserMessageList<T, MT>() { _h = _hCreator.Create(), Reader = Reader, FieldInfo = FieldInfo };
        }

    }



    internal class FieldSerialiserMessageList<T, MT> : FieldSerialiser<T>//MT is Message Type
        where MT : class
    {
        public ObjectSerialiser<MT> _h;
        private IEnumerable<MT> _value;
        public Func<T, IEnumerable<MT>> Reader { get; set; }

        public sealed override void ReadValueFromTAndWriteHeader(T value, StreamWrita sw)
        {
            if ((_value = Reader(value)) == null)
                sw.HeaderWrite0();
            else
                sw.HeaderWrite1();
        }
        public sealed override void WriteValue(StreamWrita sw)
        {
            if (_value == null) return;
            foreach (MT item in _value)
            {
                if (item == null)
                {
                    sw.HeaderWrite01();//There is an item but it is null. Not commonly expected.
                }
                else
                {
                    sw.HeaderWrite11();//There is an item, it follows.
                    _h.WriteFieldData(item, sw);
                }
            }
            sw.HeaderWrite0();//There are no more items in the list.
            sw.HeaderCommit();
            _value = null;
        }
        public sealed override void WriteMetadata(StreamWrita sw)
        {
            base.WriteMetadata(sw);
            _h.WriteFieldMetaData(sw);
        }
    }
}
